package com.wankuma.hcm.midlet.metwit;

import METwit;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.Ticker;

/**
 * METwitの中心となるｽｸﾘｰﾝです.
 * 
 * @author Harada Hirotsugu
 */
public class MainScreen extends List implements CommandListener,
		TimeLineOperation.Callback, StatusDetailCallback {

	// Commands
	private Command cmdUpdateStatus = new Command("ｽﾃｰﾀｽ更新", Command.SCREEN, 0);
	private Command cmdGetTimeline = new Command("ﾀｲﾑﾗｲﾝ取得", Command.SCREEN, 1);
	private Command cmdBeginAutoTimeLine = new Command("ﾀｲﾑﾗｲﾝ自動取得開始",
			Command.SCREEN, 2);
	private Command cmdStopAutoTimeLine = new Command("ﾀｲﾑﾗｲﾝ自動取得停止",
			Command.SCREEN, 2);
	private Command cmdChangeTimeLine = new Command("ﾀｲﾑﾗｲﾝ変更", Command.SCREEN,
			3);
	private Command cmdNewerPage = new Command("新いﾍﾟｰｼﾞ", Command.SCREEN, 4);
	private Command cmdOlderPage = new Command("古いﾍﾟｰｼﾞ", Command.SCREEN, 5);
	private Command cmdDetailStatus = new Command("ｽﾃｰﾀｽを開く", Command.ITEM, 100);
	private Command cmdConfig = new Command("環境設定", Command.SCREEN, 200);
	private Command cmdExit = new Command("終了", Command.EXIT, 201);

	// Objects
	private Display display;
	/**
	 * 既読ｽﾃｰﾀｽのﾌｫﾝﾄ
	 */
	Font fntRead;
	/**
	 * 未読ｽﾃｰﾀｽのﾌｫﾝﾄ
	 */
	Font fntUnread;
	/**
	 * MainScreen,DetailScreen,UpdateScreenに共通して表示されるTicker
	 */
	private Ticker ticker = new Ticker("");
	/**
	 * 自動取得処理に使用されるTimer
	 */
	private Timer tmrTimeLine = null;
	/**
	 * 自動取得処理を実行するTimerTask
	 */
	private TimerTask ttskTimeLine = null;
	/**
	 * Tickerの一定時間後非表示に使用されるTimer
	 */
	private Timer tmrRemoveTicker = null;
	/**
	 * Tickerの一定時間後非表示に使用されるTimerTask
	 */
	private TimerTask ttskRemoveTicker = null;
	
	private Thread thrTimeLine = null;
	
	// Data
	/**
	 * 表示中のﾀｲﾑﾗｲﾝID
	 */
	private int timeLineId = Status.FRIENDS;
	/**
	 * 表示中のﾍﾟｰｼﾞ番号
	 */
	private int pageNo = 0;

	private int getTimeLineId() {
		return timeLineId;
	}

	private void setTimeLineId(int _timeLineId) {
		timeLineId = _timeLineId;
		StatusDetailScreen.getInstance().setTimeLineId(_timeLineId);
	}

	/**
	 * MainScreenを初期化します.
	 */
	public MainScreen() {
		super("METwit - Twitter client on Java ME.", List.IMPLICIT);

		display = METwit.getDisplay();

		fntRead = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
				Font.SIZE_MEDIUM);
		fntUnread = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_ITALIC,
				Font.SIZE_MEDIUM);

		// Commands
		this.addCommand(cmdUpdateStatus);
		this.addCommand(cmdGetTimeline);
		this.addCommand(cmdBeginAutoTimeLine);
		this.addCommand(cmdChangeTimeLine);
		this.addCommand(cmdOlderPage);
		this.addCommand(cmdNewerPage);
		this.addCommand(cmdDetailStatus);
		this.addCommand(cmdConfig);
		this.addCommand(cmdExit);
		this.setCommandListener(this);
	}

	/**
	 * Tickerの表示,非表示処理を行います.
	 * 
	 * @param str
	 *            Tickerに表示する文字列. nullを指定するとTickerを非表示にします.
	 */
	public void setTickerString(String str) {
		if (str == null) {
			this.setTicker(null);
			// UpdateScreen.getInstance().setTicker(null);
			StatusDetailScreen.getInstance().setTicker(null);
		} else {
			this.ticker.setString(str);
			this.setTicker(ticker);
			// UpdateScreen.getInstance().setTicker(ticker);
			StatusDetailScreen.getInstance().setTicker(ticker);
		}
	}

	/**
	 * 一定時間後にTickerを非表示にするﾀｲﾏｰを開始します.
	 * 
	 * @param dis
	 *            非表示にするまでの時間(ﾐﾘ秒)
	 */
	public void setRemoveTickerTimer(long dis) {
		tmrRemoveTicker = new Timer();
		ttskRemoveTicker = new RemoveTickerTimerTask();
		tmrRemoveTicker.schedule(ttskRemoveTicker, dis);
	}

	public void commandAction(Command c, Displayable d) {
		if (c == cmdUpdateStatus) {
			// ------------------------------
			// ｽﾃｰﾀｽ更新
			// ------------------------------
			if (tmrRemoveTicker != null)
				tmrRemoveTicker.cancel();

			display.setCurrent(UpdateScreen.getInstance());
		} else if (c == cmdGetTimeline) {
			// ------------------------------
			// ﾀｲﾑﾗｲﾝ取得
			// ------------------------------
			if (tmrRemoveTicker != null)
				tmrRemoveTicker.cancel();

			if(thrTimeLine != null && thrTimeLine.isAlive())
				return;
			
			Runnable r = new TimeLineOperation(getTimeLineId(), this);
			thrTimeLine = new Thread(r);
			thrTimeLine.start();
		} else if (c == cmdBeginAutoTimeLine) {
			// ------------------------------
			// ﾀｲﾑﾗｲﾝ自動取得開始
			// ------------------------------
			this.removeCommand(cmdBeginAutoTimeLine);
			this.addCommand(cmdStopAutoTimeLine);

			tmrTimeLine = new Timer();
			ttskTimeLine = new TimeLineTimerTask();
			tmrTimeLine.schedule(ttskTimeLine, 500);
		} else if (c == cmdStopAutoTimeLine) {
			// ------------------------------
			// ﾀｲﾑﾗｲﾝ自動取得停止
			// ------------------------------
			this.removeCommand(cmdStopAutoTimeLine);
			this.addCommand(cmdBeginAutoTimeLine);

			tmrTimeLine.cancel();
			tmrTimeLine = null;
			ttskTimeLine = null;
		} else if (c == cmdChangeTimeLine) {
			// ------------------------------
			// ﾀｲﾑﾗｲﾝ変更
			// ------------------------------
			ChangeTimeLineScreen scr = new ChangeTimeLineScreen(this,
					timeLineId);
			display.setCurrent(scr);
		} else if (c == cmdNewerPage) {
			// ------------------------------
			// 新しいﾍﾟｰｼﾞ
			// ------------------------------
			showPage(pageNo - 1);
		} else if (c == cmdOlderPage) {
			// ------------------------------
			// 古いﾍﾟｰｼﾞ
			// ------------------------------
			showPage(pageNo + 1);
		} else if (c == cmdDetailStatus || c == SELECT_COMMAND) {
			// ------------------------------
			// ｽﾃｰﾀｽを開く
			// ------------------------------
			Config config = Config.getInstance();
			int idx = this.getSelectedIndex();
			if (idx >= 0) {
				int tidx = pageNo * config.getPageCapacity() + idx;
				display.setCurrent(StatusDetailScreen.getInstance(tidx, this));
			}
		} else if (c == cmdConfig) {
			// ------------------------------
			// 環境設定
			// ------------------------------
			ConfigForm cf = new ConfigForm();
			display.setCurrent(cf);
		} else if (c == cmdExit) {
			// ------------------------------
			// 終了
			// ------------------------------
			METwit.getInstance().notifyDestroyed();
		}
	}

	/**
	 * 詳細画面とのｲﾝﾃﾞｯｸｽ同期処理を行います.
	 */
	public void detailClosedAction(int idx) {
		Config config = Config.getInstance();
		int page = idx / config.getPageCapacity();
		int sidx = idx % config.getPageCapacity();
		showPage(page);
		this.setSelectedIndex(sidx, true);
	}

	/**
	 * 取得完了後のﾍﾟｰｼﾞ表示処理を行います.
	 */
	public void gotTimeLineAction(int tlid, int cnt) {
		this.setTimeLineId(tlid);
		if (cnt != 0)
			showPage(0);
	}

	/**
	 * 現在のﾀｲﾑﾗｲﾝの指定されたﾍﾟｰｼﾞを表示します.
	 * 
	 * @param page
	 *            ﾍﾟｰｼﾞ番号
	 */
	private boolean showPage(int page) {
		Config config = Config.getInstance();
		Vector gtl = Status.getTimeLine(getTimeLineId());

		// ﾍﾟｰｼﾞ番号が負の場合実行しない.
		if (page < 0) {
			return false;
		}

		// ﾍﾟｰｼﾞに表示する項目が負の場合実行しない.
		if ((gtl.size() - page * config.getPageCapacity()) < 0) {
			return false;
		}

		this.pageNo = page;
		int size = gtl.size();
		int start = pageNo * config.getPageCapacity();

		this.setTitle("METwit (" + (page + 1) + "/"
				+ (size / config.getPageCapacity() + 1) + ")");

		this.deleteAll();
		for (int i = start; i < (start + config.getPageCapacity()) && i < size; i++) {
			Status s = (Status) gtl.elementAt(i);
			String str = s.getText() + " by " + s.getScreenName();
			int idx = this.append(str, null);
			if (!s.isReaded())
				this.setFont(idx, fntUnread);
			else
				this.setFont(idx, fntRead);
		}
		return true;
	}

	/**
	 * ﾀｲﾑﾗｲﾝの自動取得処理を行うTimerTaskです. TODO ﾒﾓﾘﾘｰｸっぽいのを解消
	 * 
	 * @author Harada Hirotsugu
	 */
	public class TimeLineTimerTask extends TimerTask implements
			TimeLineOperation.Callback {
		public TimeLineTimerTask() {

		}

		/**
		 * 取得処理をして次のﾀｲﾏｰをｾｯﾄする
		 */
		public void run() {
			Config config = Config.getInstance();
			
			ttskTimeLine = new TimeLineTimerTask();
			
			if(thrTimeLine != null && thrTimeLine.isAlive()){
				tmrTimeLine.schedule(ttskTimeLine, 5000);
				return;
			}
			
			Calendar lm = Status.getLastModified(Status.FRIENDS);
			if (lm != null) {
				long ivr = config.getTimerInterval() * 60000;
				long dis = new Date().getTime() - lm.getTime().getTime();
				if (dis < ivr) {
					tmrTimeLine.schedule(ttskTimeLine, ivr - dis);
					return;
				}
			}

			tmrTimeLine.schedule(ttskTimeLine, config.getTimerInterval());

			Runnable r = new TimeLineOperation(getTimeLineId(),
					(TimeLineOperation.Callback) ttskTimeLine);
			thrTimeLine = new Thread(r);
			thrTimeLine.start();
		}

		public void gotTimeLineAction(int tlid, int cnt) {
			// Friendsタイムラインを表示中のみ表示
			if (cnt > 0 && getTimeLineId() == Status.FRIENDS) {
				showPage(0);
			}
		}
	}

	/**
	 * Tickerの非表示処理を行うTimerTaskです.
	 * 
	 * @author Harada Hirotsugu
	 */
	public class RemoveTickerTimerTask extends TimerTask {

		public RemoveTickerTimerTask() {
		}

		public void run() {
			MainScreen mscr = METwit.getMainScreen();
			mscr.setTickerString(null);
			mscr.tmrRemoveTicker = null;
			mscr.ttskRemoveTicker = null;
		}

		public boolean cancel() {
			MainScreen mscr = METwit.getMainScreen();
			mscr.tmrRemoveTicker = null;
			mscr.ttskRemoveTicker = null;
			return super.cancel();
		}
	}
}
